﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Threading.Tasks;
using xycn.framework.Common;

namespace xycn.framework.PluginManagement
{
    /// <summary>
    /// 用于记录当前默认运行上下文中已经加载的依赖项
    /// 
    /// </summary>
    public static class GlobalContext
    {
        /// <summary>
        /// 用于保存默认运行环境程序集
        /// </summary>
        public static Dictionary<string, Assembly> defaultAssemblies =
            new Dictionary<string, Assembly>();

        /// <summary>
        /// 用于保存当前加载的插件运行环境
        /// </summary>
        public static Dictionary<string, PluginLoadContext> pluginContexts =
            new Dictionary<string, PluginLoadContext>();

        /// <summary>
        /// 更新当前默认环境中加载的程序集
        /// </summary>
        public static void RefreshCurrentLoadAssembly()
        {
            Assembly[] assem_atr = AppDomain.CurrentDomain.GetAssemblies();
            foreach (Assembly ab in assem_atr)
            {
                defaultAssemblies.Add(ab.FullName, ab);
            }
        }

        /// <summary>
        /// 在程序默认运行环境中加载指定的共享依赖库
        /// </summary>
        /// <param name="file">直接加载的库文件（带路径）</param>
        /// <param name="dependency_path">依赖库所在文件夹</param>
        /// <param name="loaded_dependency">当前已经加载了的依赖库</param>
        /// <returns></returns>
        public static void LoadDefaultSharedLibs(string sharedlib_path)
        {
            string sharedlib_absolutepath =
                MultiOSSupportExtension.CalculateAbsoluteDir(Program.RuntimeDir,
                sharedlib_path);
            
            string[] files = Directory.GetFiles(sharedlib_absolutepath);

            //在当前指定文件夹内搜索包含controller的dll，并进行注册
            foreach (string file in files)
            {
                if (!file.ToLower().EndsWith(".dll"))//文件筛选
                    continue;

                AssemblyName assembly_name =
                    new AssemblyName(Path.GetFileNameWithoutExtension(file));

                if (!defaultAssemblies.ContainsKey(assembly_name.FullName))
                {
                    try
                    {
                        Assembly ab = AssemblyLoadContext.Default.LoadFromAssemblyPath(file);
                        defaultAssemblies.Add(ab.FullName, ab);
                    }
                    catch (Exception ex)
                    { 
                    
                    }
                }
            }

            //递归遍历子目录加载
            string[] child_dirs = Directory.GetDirectories(sharedlib_absolutepath);
            foreach (string dir in child_dirs)
            {
                LoadDefaultSharedLibs(dir);
            }
        }

        /// <summary>
        /// 加载插件
        /// </summary>
        /// <param name="plugin_path"></param>
        /// <returns></returns>
        public static Assembly LoadPlugin(string plugin_path)
        {
            if (pluginContexts.ContainsKey(plugin_path)) 
            {
                return pluginContexts[plugin_path].pluginAssembly;
            }

            try
            {
                PluginLoadContext loadContext = new PluginLoadContext(plugin_path);
                Assembly ab =
                    loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(plugin_path)));

                loadContext.pluginName = plugin_path;
                loadContext.pluginAssembly = ab;

                pluginContexts.Add(plugin_path, loadContext);

                return ab;
            }
            catch (Exception ex)
            {
                Console.WriteLine("加载控制器插件时出错了，" + ex.Message);
                return null;
            }
        }
    }
}
